package animation;

import java.util.ArrayList;

/**
 * An instance of a skin linked up to a skeleton and skin component collection.
 */
public class SkinInstance {
	// creates an empty skin instance
	public SkinInstance(Skeleton skeleton, SkinComponentCollection skinComponentCollection) {
		if (skeleton == null || skinComponentCollection == null) {
			throw new IllegalArgumentException("Skeleton or skin component collection not specified");
		}
		this.skeleton = skeleton;
		this.skinComponentCollection = skinComponentCollection;
		skinComponentIndices = new ArrayList<Integer>();
		skinComponentIndices = new ArrayList<Integer>();
		skinComponentIndices.ensureCapacity(skeleton.getBoneCount());
		for (int i = 0; i < skeleton.getBoneCount(); ++i) {
			skinComponentIndices.add(-1);
		}
	}

	public SkinInstance(Skin skin, Skeleton skeleton, SkinComponentCollection skinComponentCollection) {
		this(skeleton, skinComponentCollection);
		setSkin(skin);
	}

	public void setSkin(Skin skin) {
		for (int i = 0; i < skin.getSkinnedBoneCount(); ++i) {
			Skin.SkinnedBone skinnedBone = skin.getSkinnedBone(i);
			int bone = skeleton.getBoneIndex(skinnedBone.getBoneName());
			if (bone < 0) {
				throw new IllegalArgumentException("Skin and skeleton are not compatible: " +
						"bone " + skinnedBone.getBoneName() + " not found in skeleton");
			}
			int component = skinComponentCollection.getComponentIndex(skinnedBone.getComponentName());
			if (component < 0) {
				throw new IllegalArgumentException("Skin and skin component collection not compatible: " +
						"component " + skinnedBone.getBoneName() + " not found in skin component collection");
			}
			skinComponentIndices.set(bone, component);
		}
	}

	public Skeleton getSkeleton() {
		return skeleton;
	}

	public SkinComponentCollection getSkinComponentCollection() {
		return skinComponentCollection;
	}

	public int getSkinComponentIndex(int boneIndex) {
		return skinComponentIndices.get(boneIndex);
	}

	public int getSkinComponentIndex(String boneName) {
		int boneIndex = skeleton.getBoneIndex(boneName);
		if (boneIndex < 0) {
			throw new IllegalArgumentException("Invalid bone name");
		}
		return getSkinComponentIndex(boneIndex);
	}

	public void setSkinComponent(int boneIndex, int componentIndex) {
		if (componentIndex >= skinComponentCollection.getComponentCount()) {
			throw new IllegalArgumentException("Invalid component index");
		}

		skinComponentIndices.set(boneIndex, componentIndex);
	}

	public void setSkinComponent(String boneName, int componentIndex) {
		int boneIndex = skeleton.getBoneIndex(boneName);
		if (boneIndex < 0) {
			throw new IllegalArgumentException("Invalid bone name");
		}

		if (componentIndex >= skinComponentCollection.getComponentCount()) {
			throw new IllegalArgumentException("Invalid component index");
		}

		skinComponentIndices.set(boneIndex, componentIndex);
	}

	public void setSkinComponent(int boneIndex, String componentName) {
		int componentIndex = (componentName == null) ? -1 : skinComponentCollection.getComponentIndex(componentName);
		if (componentIndex >= skinComponentCollection.getComponentCount()) {
			throw new IllegalArgumentException("Invalid component index");
		}

		skinComponentIndices.set(boneIndex, componentIndex);
	}

	public void setSkinComponent(String boneName, String componentName) {
		int boneIndex = skeleton.getBoneIndex(boneName);
		if (boneIndex < 0) {
			throw new IllegalArgumentException("Invalid bone name");
		}

		int componentIndex = (componentName == null) ? -1 : skinComponentCollection.getComponentIndex(componentName);
		if (componentIndex >= skinComponentCollection.getComponentCount()) {
			throw new IllegalArgumentException("Invalid component index");
		}

		skinComponentIndices.set(boneIndex, componentIndex);
	}

	private Skeleton skeleton;
	private SkinComponentCollection skinComponentCollection;

	// maps each bone index in skeleton to skin component index in skin component set
	// bones without skin components are mapped to -1
	private ArrayList<Integer> skinComponentIndices;
}
